# -*- coding: utf-8 -*-
"""
规则引擎
支持灵活的规则配置和复杂条件判断
"""

import logging
import fnmatch
from typing import Dict, Any, List
from datetime import datetime

logger = logging.getLogger(__name__)


class RuleEngine:
    """规则引擎"""
    
    def __init__(self, config: Dict[str, Any]):
        self.config = config
        self.rules = self._load_rules()
        logger.info(f"规则引擎初始化完成，加载了 {len(self.rules)} 条规则")
    
    def _load_rules(self) -> List[Dict]:
        """加载规则配置"""
        alert_rules = self.config.get('alert_rules', {})
        rules = []
        
        # 转换配置为规则列表
        for rule_name, rule_config in alert_rules.items():
            if rule_config.get('enabled', True):
                rules.append({
                    'name': rule_name,
                    'config': rule_config
                })
        
        return rules
    
    def should_alert_for_drop_table(self, db_name: str, table_name: str) -> tuple[bool, str]:
        """
        判断删表操作是否需要告警
        
        Returns:
            (是否告警, 告警级别)
        """
        rule = self.config.get('alert_rules', {}).get('drop_table', {})
        if not rule.get('enabled', True):
            return False, None
        
        full_name = f"{db_name}.{table_name}"
        whitelist = rule.get('whitelist', [])
        blacklist = rule.get('blacklist', [])
        
        # 黑名单优先级最高
        if self._match_any_pattern(full_name, blacklist):
            return True, rule.get('level', 'severe')
        
        # 白名单排除
        if self._match_any_pattern(full_name, whitelist):
            return False, None
        
        # 默认告警
        return True, rule.get('level', 'severe')
    
    def should_alert_for_drop_database(self, db_name: str) -> tuple[bool, str]:
        """
        判断删库操作是否需要告警
        
        Returns:
            (是否告警, 告警级别)
        """
        rule = self.config.get('alert_rules', {}).get('drop_database', {})
        if not rule.get('enabled', True):
            return False, None
        
        whitelist = rule.get('whitelist', [])
        
        # 白名单排除
        if self._match_any_pattern(db_name, whitelist):
            return False, None
        
        # 默认告警
        return True, rule.get('level', 'critical')
    
    def should_alert_for_data_fluctuation(self, db_name: str, table_name: str,
                                         partition_change_rate: float = None,
                                         row_change_rate: float = None) -> tuple[bool, str, Dict]:
        """
        判断数据量波动是否需要告警
        
        Returns:
            (是否告警, 告警级别, 详细信息)
        """
        rule = self.config.get('alert_rules', {}).get('data_fluctuation', {})
        if not rule.get('enabled', True):
            return False, None, {}
        
        partition_threshold = rule.get('partition_change_threshold', 0.3)
        row_threshold = rule.get('row_count_threshold', 0.5)
        
        details = {}
        alert_level = 'info'
        should_alert = False
        
        # 检查分区变化
        if partition_change_rate is not None and partition_change_rate >= partition_threshold:
            should_alert = True
            details['partition_change_rate'] = f"{partition_change_rate * 100:.1f}%"
            if partition_change_rate >= 0.5:
                alert_level = 'severe'
            else:
                alert_level = 'warning'
        
        # 检查行数变化
        if row_change_rate is not None and row_change_rate >= row_threshold:
            should_alert = True
            details['row_change_rate'] = f"{row_change_rate * 100:.1f}%"
            if row_change_rate >= 0.7:
                alert_level = 'severe'
            elif alert_level != 'severe':
                alert_level = 'warning'
        
        return should_alert, alert_level, details
    
    def should_alert_for_batch_delete(self, delete_count: int, time_window: int) -> tuple[bool, str]:
        """
        判断批量删除是否需要告警
        
        Returns:
            (是否告警, 告警级别)
        """
        rule = self.config.get('alert_rules', {}).get('batch_delete', {})
        if not rule.get('enabled', True):
            return False, None
        
        threshold = rule.get('threshold', 10)
        
        if delete_count >= threshold:
            return True, rule.get('level', 'critical')
        
        return False, None
    
    def _match_any_pattern(self, name: str, patterns: List[str]) -> bool:
        """
        匹配任意一个模式
        支持通配符 * 和 ?
        """
        return any(fnmatch.fnmatch(name, pattern) for pattern in patterns)
    
    def evaluate_custom_rule(self, rule_name: str, context: Dict[str, Any]) -> bool:
        """
        评估自定义规则
        
        Args:
            rule_name: 规则名称
            context: 上下文数据
        
        Returns:
            是否触发规则
        """
        # 这里可以实现更复杂的规则引擎逻辑
        # 例如支持Python表达式、条件组合等
        pass
    
    def reload_rules(self):
        """重新加载规则"""
        self.rules = self._load_rules()
        logger.info(f"规则已重新加载，共 {len(self.rules)} 条")

